package org.esk.dablog.dao.hibernate;

import org.esk.dablog.dao.EntryDAO;
import org.esk.dablog.model.Entry;
import org.esk.dablog.model.Comment;
import org.esk.dablog.model.Picture;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import java.sql.SQLException;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * This class
 * User: jc
 * Date: 22.11.2006
 * Time: 12:36:27
 * $Id:$
 * <p/>
 * warnings suppressed because Hibernate is not generic-aware
 */
@SuppressWarnings("unchecked")
public class EntryDAOImpl extends HibernateDaoSupport implements EntryDAO {

    /**
     * adds new entry
     *
     * @param entry
     * @return
     */
    public long addEntry(Entry entry) {
        return (Long) getHibernateTemplate().save(entry.getClass().getName(), entry);
    }


    /**
     * @param clazz
     * @param i     @return
     */
    public List<Entry> listEntries(final Class<? extends Entry> clazz, final int i) {
        return getHibernateTemplate().executeFind(new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException, SQLException {
                Query q = session.createQuery("from " + clazz.getName() + " e " +
                        " order by e.date desc");
                if (i > 0) {
                    q.setMaxResults(i);
                }
                return q.list();

            }
        });
    }


    /**
     * @param clazz
     * @param start
     * @param end   @return
     */
    public List<Date> listEntriesPerDate(Class<? extends Entry> clazz, Date start, Date end) {
        return getHibernateTemplate().find("select e.date from " +
                clazz.getName() + " e " +
                " where e.date >= ? and e.date <= ?",
                new Object[]{start, end});
    }

    /**
     * @param start
     * @param end   @return
     */
    public List listEntriesByDate(Class<? extends Entry> clazz, Date start, Date end) {
        return getHibernateTemplate().find("from " + clazz.getName() + " e " +
                "where e.date >= ? and e.date <=?", new Object[]{start, end});
    }

    /**
     * @param entryId
     * @return
     */
    public Entry getEntry(Class<? extends Entry> clazz, long entryId) {
        return (Entry) getHibernateTemplate().get(clazz, entryId);
    }

    /**
     * @param entry
     */
    public void updateEntry(Entry entry) {
        getHibernateTemplate().update(entry);
    }

    /**
     * lists entries of the specified class
     *
     * @param clazz
     * @return
     */
    public List listEntries(Class<? extends Entry> clazz) {
        if (clazz == null) {
            return Collections.EMPTY_LIST;
        }
        return getHibernateTemplate().find(" from " + clazz.getName());
    }

    /**
     * @param entryClasses
     * @param start
     * @param count
     * @return
     */
    public List<Entry> listEntries(final List<Class<? extends Entry>> entryClasses, final int start, final int count) {
        if (entryClasses == null || entryClasses.isEmpty()) {
            return Collections.EMPTY_LIST;
        }
        return getHibernateTemplate().executeFind(new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException, SQLException {
                StringBuffer sb = new StringBuffer();
                boolean appendComma = false;
                for (Class c : entryClasses) {
                    if (appendComma) {
                        sb.append(',');
                    }
                    sb.append(c.getName());
                    appendComma = true;
                }
                Query q = session.createQuery(" from " + Entry.class.getName() + " e where e.class in(" + sb.toString() + ")" +
                        " order by e.date desc");
                q.setFirstResult(start);
                q.setMaxResults(count);
                return q.list();
            }
        });
    }

    /**
     * returns list of visible (state < 1000) entries
     *
     * @param clazz
     * @param i
     * @return
     */
    public List listVisibleEntries(final Class<? extends Entry> clazz, final int i) {
        return getHibernateTemplate().executeFind(new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException, SQLException {
                Query q = session.createQuery("from " + clazz.getName() + " e " +
                        " where e.state < 1000 " +
                        " order by e.date desc");
                if (i > 0) {
                    q.setMaxResults(i);
                }
                return q.list();

            }
        });

    }

    /**
     * deletes the entry
     * @param entryId
     */
    public void deleteEntry(long entryId) {

        //TODO configure cascades instead
        getHibernateTemplate().bulkUpdate("delete " + Comment.class.getName() +
                " p where p.entry.id = ?", entryId);
        getHibernateTemplate().bulkUpdate("delete " + Picture.class.getName() +
                " p where p.entry.id = ?", entryId);        
        getHibernateTemplate().bulkUpdate("delete " + Entry.class.getName() +
                " p where p.id = ?", entryId);
    }
}
